﻿using AiQiuQuan.Sport.Core;
using AiQiuQuan.Sport.Model.Enums;
using AiQiuQuan.Sport.Model.Models;
using AiQiuQuan.Sport.WebApi.Repositories;
using DotNetCore.CAP;
using Microsoft.EntityFrameworkCore;

namespace AiQiuQuan.Sport.WebApi.HangfireServices
{
    /// <summary>
    /// 场馆订单自动核销定时任务
    /// </summary>
    [ReccuringJobCron("0 0/30 * * * ?")]
    public class VenueOrderAutoWriteoffHangfireService : IHangfireService
    {
        private readonly ISiteOrderRepository _siteOrderRepository;
        private readonly ISiteOrderDetailRepository _siteOrderDetailRepository;
        private readonly ICapPublisher _capPublisher;

        /// <summary>
        /// ctor
        /// </summary>
        public VenueOrderAutoWriteoffHangfireService(
            ISiteOrderRepository siteOrderRepository,
            ISiteOrderDetailRepository siteOrderDetailRepository,
            ICapPublisher capPublisher)
        {
            _siteOrderRepository = siteOrderRepository;
            _siteOrderDetailRepository = siteOrderDetailRepository;
            _capPublisher = capPublisher;
        }

        /// <summary>
        /// 执行
        /// </summary>
        public async Task ExecuteAsync()
        {
            var time = new TimeSpan(DateTimeOffset.Now.Hour, DateTimeOffset.Now.Minute, 0);
            var querable = from order in _siteOrderRepository.AsNoTracking()
                           join detail in _siteOrderDetailRepository.AsNoTracking()
                           on order.ID equals detail.SiteOrderID
                           where order.SO_State == VenueOrderStateEnum.NoUse && detail.SiteDate <= DateTimeOffset.Now.Date
                           select new
                           {
                               order.ID,
                               order.PayType,
                               order.SO_OrderNo,
                               order.VenueInfoID,
                               order.SO_ActualPrice,
                               detail.SiteDate,
                               detail.SiteStartTime
                           };
            var orderList = await querable.ToListAsync();
            var venueAccountDetaillist = new List<VenueInfoAccountDetailAddDto>();
            if (orderList.Any())
            {
                var orderIdList = new List<Guid>();
                foreach (var item in orderList.GroupBy(m => new { m.ID, m.SO_OrderNo, m.VenueInfoID, m.SO_ActualPrice, m.PayType }))
                {
                    var price = item.OrderBy(m => m.SiteStartTime).First();
                    if (price.SiteDate < DateTimeOffset.Now.Date || TimeSpan.Parse(price.SiteStartTime) <= time)
                    {
                        orderIdList.Add(item.Key.ID);
                        if (item.Key.PayType.GetValueOrDefault() != PayTypeEnum.VenueMemberCard)
                        {
                            var detail = new VenueInfoAccountDetailAddDto()
                            {
                                SourceType = VenueAccountSourceEnum.SiteOrder,
                                OperateType = VenueAccountOperateEnum.Add,
                                Amount = item.Key.SO_ActualPrice,
                                VenueID = item.Key.VenueInfoID,
                                Remark = $"核销订单：{item.Key.SO_OrderNo}；结算金额：{item.Key.SO_ActualPrice}"
                            };
                            venueAccountDetaillist.Add(detail);
                        }
                    }
                }

                var sendCount = 0;
                while (orderIdList.Count - sendCount > 0)
                {
                    var list1 = orderIdList.Skip(sendCount).Take(100).ToList();
                    var list2 = venueAccountDetaillist.Skip(sendCount).Take(100).ToList();

                    var orderBuilder = await _siteOrderRepository.UpdatePartialAsync();
                    await orderBuilder.Set(m => m.SO_State, VenueOrderStateEnum.NoEvaluate)
                        .Set(m => m.AutoWriteOffTime, DateTimeOffset.Now)
                        .Set(m => m.IsWriteOff, true)
                        .Where(m => list1.Contains(m.ID))
                        .ExecuteAsync();
                    if (list2.Any())
                    {
                        await _capPublisher.PublishAsync(MessageTopic.VENUE_ACCOUNT_DETAIL_ADD, list2);
                    }

                    sendCount += 100;
                }
            }
        }
    }
}
